//------------------------------------------------------------------------------
// <copyright file="Player.cpp" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

#include "stdafx.h"
#include "Player.h"
#include <memory>

namespace Microsoft { namespace Internal { namespace GamesTest { namespace Rpc { namespace Server { namespace TestHooks
{
	Player::Player()
		: health(-1.0f), name(nullptr), numSpells(0), spells(nullptr), weapons(nullptr), numWeapons(0)
	{
	}

	HRESULT Player::FromRpcArchive(RpcArchive& archive, Player* result)
	{
		HRESULT hr = E_FAIL;
		std::unique_ptr<RpcArchive[]> weaponsArchives(nullptr);
		RpcArchive* ptrWeaponsArchives = nullptr;

		RpcArchive statureArchive;

		if(result == nullptr)
		{
			CHK(E_INVALIDARG);
		}

		CHK(archive.GetNamedValue(L"health", &result->health));			

		DWORD nameLength = 0;
		CHK(archive.MeasureNamedStringValue(L"name", &nameLength));
		result->name = new wchar_t[nameLength];

		CHK(archive.GetNamedStringValue(L"name", result->name, nameLength, NULL));

		DWORD totalNumSpellCharacters = 0;
		CHK(archive.MeasureNamedStringCollection(L"spells", &result->numSpells, &totalNumSpellCharacters));
		result->spells = (wchar_t**)malloc((result->numSpells * sizeof(wchar_t*)) + (totalNumSpellCharacters * sizeof(wchar_t)));
		CHK(archive.GetNamedStringCollection(L"spells", result->spells, result->numSpells, (wchar_t*)(result->spells + result->numSpells), totalNumSpellCharacters));

		CHK(archive.MeasureNamedCollection(L"weapons", &result->numWeapons));
		result->weapons = new Weapon[result->numWeapons];

		weaponsArchives.reset(new RpcArchive[result->numWeapons]);
		ptrWeaponsArchives = weaponsArchives.get();
		CHK(archive.GetNamedCollection(L"weapons", ptrWeaponsArchives, result->numWeapons));

		for (DWORD i = 0; i < result->numWeapons; i++)
		{
			CHK(Weapon::FromRpcArchive(ptrWeaponsArchives[i], result->weapons + i));
		}

		CHK(archive.GetNamedValue(L"stature", &statureArchive));
		CHK(Stature::FromRpcArchive(statureArchive, &result->stature));
end:
		return hr;
	}

	HRESULT Player::ToRpcArchive(RpcArchive* result)
	{
		HRESULT hr = E_FAIL;

		std::unique_ptr<RpcArchive[]> weaponsArchives(nullptr);
		RpcArchive statureArchive;

		if(result == nullptr)
		{
			CHK(E_INVALIDARG);
		}

		CHK(result->SetNamedValue(L"health", health));
		CHK(result->SetNamedStringValue(L"name", name));
		CHK(result->SetNamedStringCollection(L"spells", spells, numSpells));

		weaponsArchives.reset(new RpcArchive[numWeapons]);
		for (DWORD i = 0; i < numWeapons; i++)
		{
			CHK(weapons[i].ToRpcArchive(weaponsArchives.get() + i));
		}

		CHK(result->SetNamedCollection(L"weapons", weaponsArchives.get(), numWeapons));

		CHK(stature.ToRpcArchive(&statureArchive));
		CHK(result->SetNamedValue(L"stature", statureArchive));
end:
		return hr;
	}

	Player::~Player()
	{
		if(name != nullptr)
		{
			delete[] name;
		}

		if(spells != nullptr)
		{
			free(spells);
		}

		if(weapons != nullptr)
		{
			delete[] weapons;
		}
	}

}}}}}}